package cn.clq.ymcc.service.impl;

import cn.clq.ymcc.constants.CourseConstants;
import cn.clq.ymcc.domain.CourseType;
import cn.clq.ymcc.dto.CourseMbxDto;
import cn.clq.ymcc.mapper.CourseTypeMapper;
import cn.clq.ymcc.service.ICourseTypeService;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author stone.chen
 * @since 2022-07-21
 */
@Service
@Slf4j
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    /**
     * @description: 没有使用springCache时的写法
     * 1.优先查询redis中有没有无限极树缓存
     * 2.有就直接返回
     * 3.没有就先查数据库，返回结果，同时将结果放到redis中
     * @param:
     * @return: java.util.List<cn.clq.ymcc.domain.CourseType>
     * @author clqlongbao
     * @date: 2022/7/21 2:23
     */
    public List<CourseType> treeData2() {
        //1.优先查询redis中有没有无限极树缓存
        Object value = redisTemplate.opsForValue().get(CourseConstants.COURSE_TYPE_TREE);
        if(value != null){
            log.info("redis查询返回");
            //2.有就直接返回
            return (List<CourseType>) value;
        }
        //3.没有就先查数据库，返回结果，同时将结果放到redis中
        log.info("mysql查询返回");
        List<CourseType> tree = tree();
        redisTemplate.opsForValue().set(CourseConstants.COURSE_TYPE_TREE,tree);
        return tree;
    }



    /**
     * @description:  使用springCache时的写法
     *      * 1.优先查询redis中有没有无限极树缓存
     *      * 2.有就直接返回
     *      * 3.没有就先查数据库，返回结果，同时将结果放到redis中
     * @param:
     * @return: java.util.List<cn.clq.ymcc.domain.CourseType>
     * @author clqlongbao
     * @date: 2022/7/21 2:53
     */
    @Override
    @Cacheable(cacheNames="coursetype", key = "'tree'")//coursetype::tree以字符串拼接的方式作为redis中的k，return的值位v
    public List<CourseType> treeData() {
        log.info("mysql查询返回");
        List<CourseType> tree = tree();
        return tree;
    }


    /**
     * @description: 课程面包屑
     * @param: courseTypeId
     * @return: java.util.List<cn.clq.ymcc.dto.CourseMbxDto>
     * @author clqlongbao
     * @date: 2022/7/27 0:38
     */
    @Override
    public List<CourseMbxDto> crumbs(Long courseTypeId) {
        List<CourseMbxDto> list = new ArrayList<>();
        //1.根据courseTypeId查询t_course_type表得到当前类型
        CourseType ownerProductType = selectById(courseTypeId);
        //2.分割类型层级并转化为list
        String[] split = ownerProductType.getPath().split("\\.");
        System.out.println(Arrays.asList(split));
        List<CourseType> courseTypes = selectBatchIds(Arrays.asList(split));
        System.out.println(courseTypes);

        courseTypes.forEach(courseType ->{
            CourseMbxDto courseMbxDto = new CourseMbxDto();
            courseMbxDto.setOwnerProductType(courseType);
            Wrapper<CourseType> wrapper = new EntityWrapper<>();
            wrapper.eq("pid",courseType.getPid());
            //3.找出每个层级的兄弟
            List<CourseType> courseTypeList = selectList(wrapper);
            courseMbxDto.setOtherProductTypes(courseTypeList);
            list.add(courseMbxDto);
        });
        System.out.println(list);
        return list;
    }


    /**
     * @description: 查询课程类型的无限极树
     * @param:
     * @return: java.util.List<cn.clq.ymcc.domain.CourseType>
     * @author clqlongbao
     * @date: 2022/7/21 1:56
     */
    private List<CourseType> tree() {
        //1.查询所有数据
        List<CourseType> courseTypes = selectList(null);
        Map<Long, CourseType> allTypes = courseTypes.stream().collect(Collectors.toMap(CourseType::getId, courseType -> courseType));
//        courseTypes.forEach(type->{
//            allTypes.put(type.getId(),type);
//        });
        //2.查找出第一层级
        List<CourseType> firstList = new ArrayList<>();
        for (CourseType type:courseTypes){
            if(type.getPid() == null || type.getPid().intValue() == 0){
                //第一层级
                firstList.add(type);
            }else{
                //3.不是第一层级，找自己的上级，并把自己加入到上级的children
                allTypes.get(type.getPid()).getChildren().add(type);
//                for (CourseType parent : courseTypes){
//                    if(parent.getId().intValue() == type.getPid().intValue() ){
//                        parent.getChildren().add(type);
//                    }
//                }
            }
        }
        return firstList;
    }

    @Override
    @CacheEvict(cacheNames="coursetype", key = "'tree'")//coursetype::tree
    public boolean insert(CourseType entity) {
        boolean insert = super.insert(entity);
//        if(insert){
//            //清除redis缓存
//            redisTemplate.delete(CourseConstants.COURSE_TYPE_TREE);
//        }
        return insert;
    }

    @Override
    @CacheEvict(cacheNames="coursetype", key = "'tree'")//coursetype::tree
    public boolean updateById(CourseType entity) {
        boolean update = super.updateById(entity);
//        if(update){
//            //清除redis缓存
//            redisTemplate.delete(CourseConstants.COURSE_TYPE_TREE);
//        }
        return update;
    }

    @Override
    @CacheEvict(cacheNames="coursetype", key = "'tree'")//coursetype::tree
    public boolean deleteById(Serializable id) {
        boolean delete = super.deleteById(id);
//        if(delete){
//            //清除redis缓存
//            redisTemplate.delete(CourseConstants.COURSE_TYPE_TREE);
//        }
        return delete;
    }
}
